package com.tianji.learning.utils;

import com.tianji.common.utils.JsonUtils;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.mapper.LearningRecordMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.DelayQueue;

/**
 * @Description RecordCacheUtil
 * @Author apeng
 * @Date 2024-12-19
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class RecordCacheUtil {

    private final StringRedisTemplate redisTemplate;
    private static final String RECORD_CACHE_PREFIX = "record:cache:";
    private final LearningLessonMapper lessonMapper;
    private final LearningRecordMapper recordMapper;
    private final DelayQueue<DelayTask<LearningRecord>> queue = new DelayQueue<>();
    private static volatile boolean begin= true;
    //防止占用主线程，这里使用线程池技术


    //程序启动时候就启动
    @PostConstruct
    public void init(){
        log.info("工具类开始消费");
        //使用jdk自带的线程池，异步处理
        CompletableFuture.runAsync(this::consumeQueue);
    }


    //消费消息
    public void consumeQueue(){
        while (begin){
            try {
                DelayTask<LearningRecord> take = queue.take();
                //获得队列中的数据
                LearningRecord data = take.getData();
                if (data == null){
                    //说明消息是空的，直接不要了
                    continue;
                }
                //查询缓存
                LearningRecord record = readCache(data.getLessonId(), data.getSectionId());
                if (record == null){
                    continue;
                }
                //对比缓存的moment和
                if(data.getMoment().equals(record.getMoment())){
                    //更新记录表
                    LearningRecord updateRecord = new LearningRecord();
                    updateRecord.setId(record.getId());
                    updateRecord.setMoment(record.getMoment());
                    recordMapper.updateById(updateRecord);
                    //如果一样，就写进数据库，更新课程表
                    LearningLesson updateLesson = new LearningLesson();
                    updateLesson.setId(record.getId());
                    updateLesson.setLatestLearnTime(LocalDateTime.now().minusSeconds(20));
                    updateLesson.setLatestSectionId(record.getSectionId());
                    lessonMapper.updateById(updateLesson);
                }

            } catch (Exception e) {
                log.info("消费消息队列出现异常",e);
            }
        }
    }



    //添加record到延迟队列中
    public void addCache(LearningRecord record){
        //添加到缓存中
        writeCache(record);
        //添加到延迟队列中
        DelayTask<LearningRecord> task = new DelayTask<>(record, Duration.ofSeconds(20));
        queue.add(task);
    }
    //将数据写进缓存中
    public void writeCache(LearningRecord record){
        String key = RECORD_CACHE_PREFIX + record.getLessonId();
        String hashKey = record.getSectionId().toString();
        String value = JsonUtils.toJsonStr(record);
        redisTemplate.opsForHash().put(key,hashKey,value);
        //设置过期事件
        redisTemplate.expire(key, Duration.ofMinutes(5));
    }


    //查询缓存
    public LearningRecord readCache(Long leassonId,Long sectionId){
        String key = RECORD_CACHE_PREFIX + leassonId;
        String hashKey = sectionId.toString();
        String json = (String) redisTemplate.opsForHash().get(key, hashKey);
        if (json == null){
            return null;
        }
        LearningRecord learningRecord = JsonUtils.toBean(json, LearningRecord.class);
        return learningRecord;
    }


    //清理缓存
    public void clearnCache(Long leassonId,Long sectionId){
        String key = RECORD_CACHE_PREFIX + leassonId;
        String hashKey = sectionId.toString();
        redisTemplate.opsForHash().delete(key,hashKey);
    }

}
